/** @file GameObject.h
    @class GameObject
    @brief Class representing all kinds of objects in the game world (model)
*/
#include "stdafx.h"
#include "OgreString.h"

#include <list>

#include "Vector3.h"
#include "PhysicsComponent.h"

#ifndef __GameObject_h_
#define __GameObject_h_
class GameObject {
public:
	/**
	* @brief Move the GameObject the specified amount (local space)
	* @param x x-wise movement
	* @param y y-wise movement
	* @param z z-wise movement
	*/
	virtual void move(float x, float y, float z);

	/**
	* @brief Constructor
	*/
	GameObject();

	/**
	* @brief Destructor
	*/
	~GameObject();

	/**
	* @brief Add a MovableObject (visual component) to the gameobject
	* @param movableObject the MovableObject to add
	*/
	virtual void addMovableObject(Ogre::MovableObject* movableObject);

	/**
	* @brief Get all MovableObjects (visual components) of the gameobject
	*/
	virtual std::list<Ogre::MovableObject*> getMovableObjects();
	
	/**
	* @brief Remove all MovableObjects (visual components) of the gameobject
	* @param sceneMgr Ogre Scenemager to remove MovableObjects from
	*/
	void destroyAllMovableObjects(Ogre::SceneManager* sceneMgr);
	
	/**
	* @brief Set which SceneNode this GameObject is attached to
	*/
	virtual void setSceneNode(Ogre::SceneNode* node);

	/**
	* @brief Get the SceneNode this GameObject is attached to
	*/
	virtual Ogre::SceneNode* getSceneNode();
	
	/**
	* @brief Get the SceneNode this GameObject wants the camera to be attached to
	*/
	virtual Ogre::SceneNode* getCameraNode();	
	
	/**
	* @brief Schedule for deletion
	*/
	void kill();

	/**
	* @brief Is Scheduled for deletion
	*/
	bool isDead();

	/**
	* @brief Set the unique ID, used for network communication
	*/
	void setID(unsigned int newID);

	/**
	* @brief Get the unique ID, used for network communication
	*/
	unsigned int getID();

	/**
	* @brief Update the interal logic of the gameobject (called each frame)
	*/
	virtual void updateLogic() = 0;

	/**
	* @brief Create the visual components for this gameobject
	* @param sceneMgr Ogre Scenemager to add the movable objects to
	* @param id The Id to use as part of the unique Ogre ID-string
	*/
	virtual void createMovableObject(Ogre::SceneManager* sceneMgr, unsigned int id) = 0;

	/**
	* @brief Triggered when adding a  gameobject to a model
	*/
	virtual void addedToModel() {}

	/**
	* @brief Get the position of a scenenode
	*/
	Ogre::Vector3 getPosition(Ogre::Node* node);

	/**
	* @brief Set the position of this Gameobject
	*/
	void setPosition(Ogre::Vector3 pos);

	/**
	* @brief Triggered when attaching the camera to a gameobject
	*/
	virtual void whenCameraAttached() {}

	/**
	* @brief Triggered when detaching the camera to a gameobject
	*/
	virtual void whenCameraDetached() {}

	/**
	* @brief Get the PhysicsComponent of this gameobject (if any)
	*/
	PhysicsComponent* getPhysicsComponent();

	/**
	* @brief Set the orientation of this gameobject
	*/
	void setOrientation(Ogre::Quaternion orientation);

	/**
	* @brief Set Orientation and Position of this gameobject (safely with physics engine)
	*/
	void synchPositionAndOrientation(Ogre::Vector3 position, Ogre::Quaternion orientation);
	

protected:
	/**
	* @brief The scenenode that this gameobject is associated with
	*/
	Ogre::SceneNode* m_node;
	
	std::list<Ogre::MovableObject*> m_movableObjects;
	PhysicsComponent* m_physicsComponent;

private:
	/**
	* @brief Scheduled for deletion
	*/
	bool m_dead;
	
	/**
	* @brief Unique ID-number
	*/
	unsigned int m_ID;
};

#endif //#ifndef __GameObject_h_